etimes = [];
fvals = [];
postdim = [];
nnzz = [];

Z = Z_init;
V = V_init;

maxacc = 0;
minfval = inf;
loopi = numel(postdim) + 1;
cnvg = 0;
earlystop = 0;

while true
    [Z,V,etime,fval] = mcmc(X, Z, V, ...
        alphav, sigmax, sigmaz, sigmav, poisstrunc, ...
        algtype, loopi);
    K = sum(any(Z));

    etimes = [etimes, etime];
    fvals = [fvals, fval];
    postdim = [postdim, K];
    nnzz = [nnzz, nnz(Z)];

    fprintf('%d: K = %d, fval = %.4f, nnz(Z) = %d\n', loopi, K, fval(2), nnz(Z));

    if cachiter
        parsave([savedir filesep 'opts.mat'], ...
            Z, V, ...
            etimes, fvals, postdim, nnzz, ...
            alphav, sigmaz, sigmav, sigmax, ...
            poisstrunc, algtype, maxiter, burnin, false);
    end

    if algtype == 2
        if fval > minfval
            cnvg = cnvg + 2;
        else
            if all(deviation({minfval}, {fval}) < 1e-5)
                cnvg = cnvg + 1;
            else
                cnvg = 0;
            end
            minfval = fval;
        end
    else
        if all(deviation({minfval}, {fval}) < 1e-5)
            cnvg = cnvg + 1;
        else
            cnvg = 0;
        end
        minfval = min(minfval, fval);
    end
    if cnvg == 10 || loopi == maxiter || K > 2000
        break;
    end
    loopi = loopi + 1;
end

parsave([savedir filesep 'opts.mat'], ...
    Z, V, ...
    etimes, fvals, postdim, nnzz, ...
    alphav, sigmaz, sigmav, sigmax, ...
    poisstrunc, algtype, maxiter, burnin, false);

if algtype == 2 || algtype == 4
    tvals = fvals(:);
    tidx = find([1; (tvals(2:end)-tvals(1:end-1)) > 0]);
    tidx = ceil(tidx/size(fvals,1));
    tidx = tidx(tidx>1);
    assert(numel(unique(tidx))==numel(tidx));
    assert(all((postdim(tidx-1)~=postdim(tidx) | nnzz(tidx-1)>nnzz(tidx))));
end